home *** CD-ROM | disk | FTP | other *** search
/ Power Programmierung / Power-Programmierung (Tewi)(1994).iso / magazine / drdobbs / 1989 / 03 / johnson.lst < prev    next >
File List  |  1989-02-10  |  48KB  |  1,360 lines

  1. _DYNAMIC LINK LIBRARIES UNDER MICROSOFT WINDOWS_
  2. by Margaret Johnson and Mark Solinski
  3.  
  4.  
  5. [LISTING ONE]
  6.  
  7. /****************************************************************************
  8.  * MODULE: HELPLIB.C
  9.  * COMMENTS: contains the functions Screen and Topics (see HELPDLG.C)
  10.  ****************************************************************************/
  11. #include  <windows.h>          /* used by all modules written for Windows */
  12. #include  "helplib.h"          /* library's include file */
  13. #define   HELPLIB
  14. #include  "prothelp.h"          /* function prototypes */
  15. /****************************************************************************
  16.  * external variables
  17.  ****************************************************************************/
  18. extern HANDLE hInst;  /* set by the initialization function in libinitc.c */
  19. /****************************************************************************
  20.  * global variables
  21.  ****************************************************************************/
  22. LPSCREEN    lpsc;
  23. BOOL        TOPICS;
  24. BOOL        SCR;
  25.  /****************************************************************************
  26.  * Local variables
  27.  ****************************************************************************/
  28.  static FARPROC     lpfnScreenDlgProc;
  29.  static FARPROC     lpfnTopicsDlgProc;
  30. /************************************************************************
  31.  * FUNCTION: Screen
  32.  * PURPOSE:  Display help text on a topic.
  33.  ************************************************************************/
  34. BOOL FAR PASCAL Screen( LPSCREEN sc )
  35. {MSG     msg;
  36.  HWND    hWnd;
  37.  LockData(0);
  38.  lpsc = sc;
  39.  
  40.  if (!(lpfnScreenDlgProc = MakeProcInstance(ScreenDlgProc,hInst)))
  41.     return FALSE;
  42.  
  43.  if (!(hWnd = CreateDialog(hInst,"HELP_BOX",GetActiveWindow(),
  44.                           lpfnScreenDlgProc)))
  45.     return FALSE;
  46.  while (GetMessage (&msg,NULL,0,0))
  47.     {if (!IsDialogMessage(hWnd,&msg) )
  48.        {TranslateMessage(&msg);
  49.         DispatchMessage(&msg);
  50.        }
  51.     }
  52.  
  53.  FreeProcInstance(lpfnScreenDlgProc);
  54.  
  55.  if (TOPICS)
  56.     {Topics(lpsc);
  57.     }
  58.  
  59.  UnlockData(0);
  60.  return TRUE;
  61. }
  62. /************************************************************************
  63.  * FUNCTION: Topics
  64.  * PURPOSE:  to present a listbox of currently available help topics.
  65.  ************************************************************************/
  66. VOID FAR PASCAL Topics( LPSCREEN sc )
  67.  
  68. {LockData(0);
  69.  lpsc = sc;
  70.  
  71.  lpfnTopicsDlgProc = MakeProcInstance(TopicsDlgProc,hInst);
  72.  DialogBox(hInst,"TOPICS_BOX",GetActiveWindow(),lpfnTopicsDlgProc);
  73.  FreeProcInstance(lpfnTopicsDlgProc);
  74.  
  75.  if (SCR)
  76.     {Screen(lpsc);
  77.     }
  78.  
  79.  UnlockData(0);
  80.  return;
  81. }
  82.  
  83.  
  84. [LISTING TWO]
  85.  
  86. /****************************************************************************
  87.  * FILE: helplib.rc
  88.  * PURPOSE:resource file for the helplib DLL
  89.  ***************************************************************************/
  90. #include <style.h>
  91. #include "helplib.h"
  92. #define  TABGRP (WS_TABSTOP | WS_GROUP)
  93.  
  94. VSRUNTIME   TEXT     vsruntime.asc
  95. CAVEATS     TEXT     caveats.asc
  96. COOKBOOK    TEXT     cookbook.asc
  97. REF         TEXT     ref.asc
  98. A           TEXT     a.asc
  99. B           TEXT     b.asc
  100. C           TEXT     c.asc
  101.  
  102. STRINGTABLE
  103.    BEGIN
  104.        IDS_MEMERROR    "Out of Memory"
  105.        VSRUNTIME,      "versus run time libraries"
  106.        CAVEATS,        "caveats"
  107.        COOKBOOK,       "cookbook"
  108.        REF,            "references"
  109.        A,              "a"
  110.        B,              "b"
  111.        C,              "c"
  112.    END
  113.  
  114. rcinclude  HELP.dlg
  115. rcinclude  TOPICS.dlg
  116.  
  117.  
  118.  
  119. [LISTING THREE]
  120.  
  121. /***************************************************************************
  122.  * FILE: helplib.h
  123.  * PURPOSE: include file for the helplib DLL
  124.  **************************************************************************/
  125. typedef struct {
  126.      WORD   wScreen;
  127.      WORD   wStart;
  128.      WORD   wEnd;
  129.     }SCREEN, FAR * LPSCREEN, NEAR *NPSCREEN;
  130. #define ID_SCREEN_HELP         100
  131. #define ID_LB_TOPICS           101
  132. #define ID_NEXT_HELP           102
  133. #define ID_PREVIOUS_HELP       103
  134. #define ID_TOPICS_HELP         104
  135. #define ID_SCROLL_HELP         105
  136.  
  137. #define VSRUNTIME              300
  138. #define CAVEATS                301
  139. #define COOKBOOK               302
  140. #define REF                    303
  141.  
  142. #define A                      500
  143. #define B                      501
  144. #define C                      502
  145.  
  146. #define IDS_MEMERROR           1000
  147.  
  148.  
  149.  
  150. [LISTING FOUR]
  151.  
  152. /**************************************************************************
  153.  * MODULE: HELPDLG.C
  154.  **************************************************************************/
  155.  
  156. #include <windows.h>         /* required for all Windows applications */
  157. #include "helplib.h"         /* library's include file */
  158. #define  HELPLIB
  159. #include "prothelp.h"        /* function prototypes */
  160. #include "string.h"          /* strlen */
  161.  
  162. /*************************************************************************
  163.  * to allow multiple screens from different apps/instances
  164.  *************************************************************************/
  165. typedef struct screenStruct {
  166.     WORD                wScreen;
  167.     WORD                wStart;
  168.     WORD                wEnd;
  169.     int                 nPage;
  170.     int                 nTopics;
  171.     int                 nNumLines;
  172.     HWND                hScroll;
  173.     int                 nVscrollPos;
  174.    }HELPSCREEN, *NPHELPSCREEN;
  175. /****************************************************************************
  176.  * local variables
  177. ****************************************************************************/
  178. #define   GWW_SCREENHANDLE  0 
  179. #define   MAXBUFLEN        80
  180. #define   MAXLINES        250
  181. #define   LOCAL        static
  182. /*************************************
  183.  * scroll bar positioning variables
  184. *************************************/
  185. LOCAL int      nVscrollMax;
  186. /*************************************
  187.  * buffer to hold the help text
  188. *************************************/
  189. LOCAL char      szText[MAXLINES][MAXBUFLEN];
  190. /*******************************************
  191.  * screen information
  192.  *******************************************/
  193. LOCAL NPHELPSCREEN sptr;
  194. /****************************************************************************
  195.  * local function prototypes
  196. ****************************************************************************/
  197. LOCAL VOID   NEAR getText         ( VOID );
  198. LOCAL VOID   NEAR setScroll       ( VOID );
  199. LOCAL VOID   NEAR setNewHelp      ( HWND );
  200. LOCAL HANDLE NEAR setToScreen     ( HWND );
  201. LOCAL BOOL   NEAR differentScreen ( HWND );
  202. LOCAL BOOL   NEAR initScreen      ( HWND );
  203. LOCAL VOID   NEAR freeScreen      ( HANDLE );
  204. /****************************************************************************
  205.  * external variables
  206. ****************************************************************************/
  207. extern HANDLE   hInst; /* set by the initialization function in libinitc.c */
  208. extern LPSCREEN lpsc;  /* passed in by the calling function */
  209. extern BOOL     TOPICS;/* used by ScreenDlgProc when the user requests Topics */
  210. extern BOOL     SCR;   /* used by TopicsDlgProc when the use requests Help */
  211. /****************************************************************************
  212.  * Function: ScreenDlgProc
  213.  * Purpose:  To respond to the Push Buttons: Topics, Next, Previous, and
  214.  *      Cancel on the Screen() dialog box.
  215.  ****************************************************************************/
  216. BOOL  FAR  PASCAL  ScreenDlgProc(HWND hDlg, WORD wMessage, WORD wParam,
  217.                                  LONG lParam)
  218.  {int             i;
  219.   static BOOL     bImoved=FALSE;
  220.   HWND            hWndScreen;
  221.   HANDLE          hScreen;
  222.   switch(wMessage)
  223.      {
  224.       case WM_INITDIALOG:
  225.         hScreen = setToScreen(hDlg);
  226.         sptr->nTopics = sptr->wEnd - sptr->wStart + 1;
  227.         sptr->hScroll = GetDlgItem(hDlg,ID_SCROLL_HELP);
  228.         getText();
  229.         LocalUnlock(hScreen);
  230.         break;
  231.       case WM_MOVE:
  232.         bImoved=TRUE;
  233.         break;
  234.       case WM_VSCROLL:
  235.         if (bImoved)
  236.           {hScreen = setToScreen(hDlg);
  237.            getText();
  238.            setScroll();
  239.            LocalUnlock(hScreen);
  240.            bImoved=FALSE;
  241.           }
  242.         hWndScreen = GetWindow(hDlg,GW_CHILD);
  243.         SendMessage(hWndScreen,WM_VSCROLL,wParam,lParam);
  244.         break;
  245.       case WM_COMMAND:
  246.          hScreen = setToScreen(hDlg);
  247.          hWndScreen = GetWindow(hDlg,GW_CHILD);
  248.          switch(wParam)
  249.            {
  250.             case ID_PREVIOUS_HELP:
  251.                sptr->wScreen = sptr->wStart + (sptr->wScreen-sptr->wStart+
  252.                                  (sptr->nTopics-1)) % sptr->nTopics;
  253.                setNewHelp(hWndScreen);
  254.                LocalUnlock(hScreen);  
  255.                break;
  256.             case ID_NEXT_HELP:
  257.                sptr->wScreen = sptr->wStart + (sptr->wScreen-sptr->wStart+1)
  258.                                              %sptr->nTopics;
  259.                setNewHelp(hWndScreen);
  260.                LocalUnlock(hScreen);
  261.                break;
  262.             case ID_TOPICS_HELP:
  263.                TOPICS = TRUE;
  264.             case IDCANCEL:
  265.                freeScreen(hScreen);
  266.                DestroyWindow(hDlg);
  267.                break;
  268.             default:
  269.                return FALSE;
  270.            }
  271.          break;
  272.       case WM_ACTIVATE:  /* when the dialog is activated, check to
  273.                           * see if the correct screen mode is
  274.                           * is selected.
  275.                           */
  276.          if (!wParam)
  277.             break;
  278.       case WM_PAINT: /* User could be switching 'tween n application's
  279.                       * (or n instances) Help Dialogs
  280.                       */
  281.          hScreen = setToScreen(hDlg);
  282.          if (differentScreen(hDlg))
  283.            {getText();
  284.            }
  285.          if (WM_ACTIVATE == wMessage)
  286.            {SetFocus(sptr->hScroll);
  287.             setScroll();
  288.            }
  289.          LocalUnlock(hScreen);
  290.          return FALSE;
  291.       default:
  292.          return FALSE;
  293.      }
  294.   return TRUE;
  295.  }
  296. /****************************************************************************
  297.  * Function: ScreenWndProc
  298.  * Purpose: To respond to messages received by the Screen() window.
  299.  * Notes:   The WM_VSCROLL, WM_PAINT message handling was derived from
  300.  *        Programming Windows by Charles Petzold, pp. 117-122.
  301.  ****************************************************************************/
  302. long FAR PASCAL  ScreenWndProc(HWND hWnd, WORD wMessage, WORD wParam,
  303.                                LONG lParam)
  304. {PAINTSTRUCT ps;
  305.  LOCAL               int          xChar,yChar;
  306.  LOCAL               int          yClient;
  307.  LOCAL               TEXTMETRIC   tm;
  308.  int                i;
  309.  int                nVscrollInc;
  310.  int                nPaintBeg,nPaintEnd;
  311.  HDC                hDC;
  312.  HANDLE             hScreen;
  313.  switch(wMessage)
  314.    {
  315.     case WM_CREATE:
  316.         if (!initScreen(hWnd))
  317.             break;
  318.         hDC = GetDC(hWnd);
  319.         GetTextMetrics(hDC,&tm);
  320.         ReleaseDC(hWnd,hDC);
  321.         xChar = tm.tmAveCharWidth;
  322.         yChar = tm.tmHeight + tm.tmExternalLeading;
  323.         TOPICS = FALSE;
  324.         break;
  325.     case WM_SIZE:
  326.         hScreen = GetWindowWord(hWnd,GWW_SCREENHANDLE);
  327.         sptr = (NPHELPSCREEN)LocalLock(hScreen);
  328.         yClient = HIWORD(lParam);
  329.         sptr->nPage = yClient / yChar ;
  330.         LocalUnlock(hScreen);
  331.         break;
  332.     case WM_SETFOCUS:
  333.         hScreen = GetWindowWord(hWnd, GWW_SCREENHANDLE);
  334.         sptr = (NPHELPSCREEN)LocalLock(hScreen);
  335.         SetFocus(sptr->hScroll);
  336.         LocalUnlock(hScreen);
  337.         break;
  338.     /* the WM_VSCROLL message is sent by the ScreenDlgProc, which has
  339.      * already taken care of sptr 
  340.      */
  341.     case WM_VSCROLL:     
  342.         switch (wParam)
  343.            {
  344.             case SB_TOP:
  345.                nVscrollInc = -sptr->nVscrollPos;
  346.                break;
  347.             case SB_BOTTOM:
  348.                nVscrollInc = nVscrollMax - sptr->nVscrollPos;
  349.                break;
  350.             case SB_LINEUP:
  351.                nVscrollInc = -1;
  352.                break;
  353.             case SB_LINEDOWN:
  354.                nVscrollInc = 1;
  355.                break;
  356.             case SB_PAGEUP:
  357.                nVscrollInc = min(-1, -sptr->nPage) ;
  358.                break;
  359.             case SB_PAGEDOWN:
  360.                nVscrollInc = max(1, sptr->nPage) ;
  361.                break;
  362.             case SB_THUMBPOSITION:
  363.                nVscrollInc = LOWORD(lParam) - sptr->nVscrollPos;
  364.                break;
  365.             default:
  366.                nVscrollInc = 0;
  367.            }
  368.         if (nVscrollInc = max(-sptr->nVscrollPos,
  369.             min(nVscrollInc, nVscrollMax - sptr->nVscrollPos)))
  370.            {sptr->nVscrollPos += nVscrollInc;
  371.             ScrollWindow(hWnd, 0, -yChar * nVscrollInc, NULL, NULL);
  372.             UpdateWindow(hWnd);
  373.             SetScrollPos(sptr->hScroll,SB_CTL,sptr->nVscrollPos,TRUE);
  374.            }
  375.         break;
  376.     case WM_PAINT:
  377.        hScreen = GetWindowWord(hWnd, GWW_SCREENHANDLE);
  378.        sptr = (NPHELPSCREEN)LocalLock(hScreen);
  379.        BeginPaint( hWnd, &ps );
  380.        nPaintBeg = max(0,sptr->nVscrollPos + ps.rcPaint.top/yChar - 1);
  381.        nPaintEnd = min(sptr->nNumLines,
  382.                     sptr->nVscrollPos + ps.rcPaint.bottom / yChar);
  383.        for (i=nPaintBeg; i < nPaintEnd; ++i)
  384.            {TextOut(ps.hdc,xChar,yChar * (1 - sptr->nVscrollPos+i),
  385.                 szText[i],strlen(szText[i]));
  386.             }
  387.        EndPaint(hWnd,&ps);
  388.        LocalUnlock(hScreen);
  389.        break;
  390.     case WM_DESTROY:
  391.        PostQuitMessage(0);
  392.        break;
  393.     default:
  394.         return DefWindowProc( hWnd, wMessage, wParam, lParam );
  395.    }
  396.  return 0L;
  397. }
  398. /****************************************************************************
  399.  * Function: TopicsDlgProc
  400.  * Purpose: To respond to the list box and push button messages
  401.  *        of the Topics() dialog box.
  402.  ****************************************************************************/
  403. BOOL  FAR  PASCAL  TopicsDlgProc(HWND hDlg, WORD wMessage, WORD wParam,
  404.                                  LONG lParam)
  405.  {int i;
  406.   LOCAL char szBuff[MAXBUFLEN];
  407.  
  408.   switch(wMessage)
  409.      {
  410.       case WM_INITDIALOG:
  411.         SetSysModalWindow(hDlg);
  412.         for (i=lpsc->wStart;i<=lpsc->wEnd;++i)
  413.            {LoadString(hInst,i,szBuff,MAXBUFLEN);
  414.             SendDlgItemMessage(hDlg,ID_LB_TOPICS,LB_ADDSTRING,0,
  415.                                     (LONG)(LPSTR)szBuff);
  416.            }
  417.         SendDlgItemMessage(hDlg,ID_LB_TOPICS,LB_SETCURSEL,0,0L);
  418.         SCR = FALSE;
  419.         break;
  420.       case WM_COMMAND:
  421.          switch(wParam)
  422.            {
  423.             case ID_LB_TOPICS:
  424.                if ((HIWORD(lParam)) != LBN_DBLCLK)
  425.                   {break;
  426.                   }
  427.             case IDOK:
  428.                lpsc->wScreen = (WORD)SendDlgItemMessage(hDlg,ID_LB_TOPICS,
  429.                                LB_GETCURSEL,0,0L) + lpsc->wStart;
  430.                SCR=TRUE;
  431.             case IDCANCEL:
  432.                EndDialog(hDlg,TRUE);
  433.                break;
  434.             default:
  435.                return FALSE;
  436.            }
  437.          break;
  438.       default:
  439.          return FALSE;
  440.      }
  441.   return TRUE;
  442.  }
  443. /****************************************************************************
  444.  * Function: getText
  445.  * Purpose: To retrieve the help text for the current screen from the
  446.  *        Help library's resource file.
  447.  ****************************************************************************/
  448. LOCAL VOID NEAR getText( )
  449.   {LPSTR   lpText,lpTextBeg;
  450.    HANDLE  hRes;
  451.    hRes = LoadResource(hInst,
  452.           FindResource(hInst,MAKEINTRESOURCE(sptr->wScreen),"TEXT"));
  453.    lpText = LockResource(hRes);
  454.    sptr->nNumLines=0;
  455.    lpTextBeg = lpText;
  456.    while (*lpText != '\0' && *lpText != '\x1A' )
  457.         {if (*lpText == '\r')
  458.            {*lpText = '\0';
  459.             lstrcpy(szText[sptr->nNumLines++],lpTextBeg);
  460.             if (sptr->nNumLines >= MAXLINES)
  461.                 break;
  462.             *lpText='\r';
  463.             lpText = AnsiNext(lpText);
  464.             if (*lpText = '\l')
  465.                 lpText = AnsiNext(lpText);
  466.             lpTextBeg = lpText;
  467.            }
  468.          else
  469.            lpText = AnsiNext(lpText);
  470.         }
  471.    *lpText = '\0';
  472.    lstrcpy(szText[sptr->nNumLines++],lpTextBeg);
  473.    GlobalUnlock(hRes);
  474.    FreeResource(hRes);
  475.   }
  476. /****************************************************************************
  477.  * Function: setScroll
  478.  * Purpose: To set the scroll bar control's range and initial position.
  479.  ****************************************************************************/
  480. LOCAL VOID NEAR setScroll( )
  481.   {nVscrollMax = max(0, sptr->nNumLines + 2 - sptr->nPage);
  482.    SetScrollRange(sptr->hScroll, SB_CTL,0, nVscrollMax, FALSE);
  483.    SetScrollPos  (sptr->hScroll, SB_CTL,sptr->nVscrollPos,TRUE);
  484.   }
  485. /****************************************************************************
  486.  * Function: setNewHelp
  487.  * Purpose: Get the right screen help info
  488.  ****************************************************************************/
  489. LOCAL VOID NEAR setNewHelp(HWND hWnd)
  490.  {sptr->nVscrollPos = 0;
  491.   getText();
  492.   setScroll();
  493.   InvalidateRect(hWnd,NULL,TRUE);
  494.   SetFocus(sptr->hScroll);
  495.  }
  496. /****************************************************************************
  497.  * Function: setToScreen
  498.  * Purpose: Lock the screen pointer to the correct screen info.
  499.  ****************************************************************************/
  500. LOCAL HANDLE NEAR setToScreen(HWND hWnd )
  501. {HANDLE       hScreen;
  502.  HWND         hWndScreen;
  503.  hWndScreen   = GetWindow(hWnd,GW_CHILD);
  504.  hScreen      = GetWindowWord(hWndScreen, GWW_SCREENHANDLE);
  505.  sptr         = (NPHELPSCREEN)LocalLock( hScreen );
  506.  return hScreen;
  507. }
  508. /****************************************************************************
  509.  * Function: differentScreen
  510.  * Purpose: Find out if hDlg references the same window as the last call
  511.  ****************************************************************************/
  512. LOCAL BOOL NEAR differentScreen(HWND hDlg)
  513. {LOCAL  HWND   hWnd = NULL;
  514.  if (hWnd != hDlg)
  515.    {hWnd = hDlg;
  516.     return TRUE;
  517.    }
  518.  return FALSE;
  519. }
  520. /****************************************************************************
  521.  * Function: initScreen
  522.  * Purpose: Set up the screen on a WM_CREATE message.
  523.  ****************************************************************************/
  524. LOCAL BOOL NEAR initScreen(HWND hWnd)
  525.  {HANDLE hScreen;
  526.   char   szMemErr[15];
  527.   if (!(hScreen = LocalAlloc(LHND,sizeof(HELPSCREEN))))
  528.     {LoadString(hInst,IDS_MEMERROR,szMemErr,15);
  529.      MessageBox( GetParent(hWnd), szMemErr, NULL, MB_ICONEXCLAMATION);
  530.      return FALSE;
  531.     }
  532.   sptr = (NPHELPSCREEN)LocalLock(hScreen);
  533.   sptr->wScreen = lpsc->wScreen;
  534.   sptr->wStart = lpsc->wStart;
  535.   sptr->wEnd = lpsc->wEnd;
  536.   LocalUnlock(hScreen);
  537.   SetWindowWord( hWnd, GWW_SCREENHANDLE, hScreen );
  538.   return TRUE;
  539.  }
  540. /****************************************************************************
  541.  * Function: freeScreen
  542.  * Purpose: All done with the screen, so release the memory.
  543.  ****************************************************************************/
  544. LOCAL VOID NEAR freeScreen(HANDLE hScreen)
  545. {lpsc->wScreen = sptr->wScreen;
  546.  lpsc->wEnd    = sptr->wEnd;
  547.  lpsc->wStart  = sptr->wStart;
  548.  LocalUnlock(hScreen);
  549.  LocalFree(hScreen);
  550. }
  551.  
  552. [LISTING FIVE]
  553.  
  554. /*
  555.  * Utilities library C language initialization.
  556.  */
  557. #include <windows.h>
  558. #include "helplib.h"
  559. #include "prothelp.h"
  560. /**********************************************************************
  561.  * function prototypes
  562.  **********************************************************************/
  563. #define LOCAL  static
  564. int         NEAR PASCAL LibInitC       ( HANDLE );
  565. LOCAL BOOL  NEAR        registerWindow ( VOID );
  566. /**********************************************************************
  567.  * Global vars
  568.  **********************************************************************/
  569. HANDLE      hInst;
  570. /**********************************************************************
  571.  * C init called from the asm entry point init.
  572.  * We require that the library have exactly one DS. See libinita.asm.
  573.  * The DS can (should) be moveable.
  574.  ***********************************************************************/
  575. int NEAR PASCAL LibInitC(HANDLE hInstance)
  576. {
  577.     hInst = hInstance;
  578.     return(registerWindow());
  579. }
  580. /************************************************************************/
  581. LOCAL BOOL  NEAR registerWindow ( )
  582. {WNDCLASS WndClass;         /* Window class structure */
  583.  WndClass.style           = CS_HREDRAW | CS_VREDRAW;
  584.  WndClass.lpfnWndProc     = ScreenWndProc;
  585.  WndClass.cbClsExtra      = 0;
  586.  WndClass.cbWndExtra      = sizeof(HANDLE);
  587.  WndClass.hInstance       = hInst;
  588.  WndClass.hIcon           = NULL;
  589.  WndClass.hCursor         = LoadCursor(NULL, IDC_ARROW);
  590.  WndClass.hbrBackground   = COLOR_WINDOW+1;
  591.  WndClass.lpszMenuName    = NULL;
  592.  WndClass.lpszClassName   = "Screen";
  593.  
  594.  return RegisterClass(&WndClass);
  595.  
  596. }
  597.  
  598. [LISTING SIX]
  599.  
  600. ; LIBINITA.ASM - - - Define entry point and perform initialization
  601. ;                    for libraries that have their own data segments.
  602.         TITLE   LIBINITA
  603. ?PLM = 1
  604. ?WIN = 1
  605. memM = 1
  606.  
  607. .xlist
  608. include cmacros.inc
  609. .list
  610.  
  611. externFP    <LocalInit>
  612. externFP    <UnlockSegment>
  613. externNP    <LibInitC>
  614. ;
  615. ;   cx = size of the heap as defined in the .def file.
  616. ;   di = "Instance handle". This is the C hInstance passed to WinMain.
  617. ;        NOTE: For a WINDOWS library, hModule is interchangeable with
  618. ;           hInstance.
  619. ;        This is a handle to the global object containing the DS if there
  620. ;        is one. If there is no DS for a library, it is the module handle,
  621. ;        which is also a pointer to the module since that's a fixed global
  622. ;        object.
  623. ;        NOTE: The meaning and contents of hInstance are undocumented and
  624. ;           should not be relied upon. That is, you may asuume that the value
  625. ;           in di may be passed to any routine expecting hInstance. Making
  626. ;           any other assumptions is VERY dangerous since the contents of
  627. ;           hInstance may change in future versions.
  628. ;   ds = data segment for our heap.
  629. ;   es:si = pointer to the command line.
  630.  
  631. _INIT SEGMENT BYTE PUBLIC   'CODE'
  632. assume CS: _INIT            ; ???? assume vs assumes? ???????????????????
  633. assumes DS,NOTHING          ; ???? assume vs assumes? ???????????????????
  634. assumes ES,NOTHING          ; ???? assume vs assumes? ???????????????????
  635.  
  636. cProc   LibInitA, <FAR, PUBLIC, NODATA>, <si,di>
  637. cBegin
  638.     xor     ax,ax                   ; Return failure if there is no heap.
  639.     jcxz    ourexit
  640.     cCall   LocalInit,<ds,ax,cx>    ; Set up our DS for doing LocalAllocs.
  641.  
  642.     or      ax,ax
  643.     jz      ourexit
  644.  
  645.     cCall   LibInitC,<di>           ; Do any C initialization.
  646.                                     ; di = hInstance.
  647.     push    ax                      ; Save the return value.
  648.     mov     ax,-1
  649.     cCall   UnlockSegment,<ax>      ; NOTE that we leave DS unlocked.
  650.                                     ; This implies that we must use
  651.                                     ; Lock/UnlockData as we enter and
  652.                                     ; any routines which access our
  653.                                     ; data segment.
  654.     pop     bx
  655.  
  656.     or      ax,ax                   ; Check if either one failed.
  657.     jz      ourexit
  658.     or      bx,bx
  659.     jnz     ourexit
  660.     xor     ax,ax
  661.  
  662. ourexit:
  663. cEnd
  664. _INIT ENDS
  665. end LibInitA
  666.  
  667. [LISTING SEVEN]
  668.  
  669. LIBRARY      helplib
  670. DESCRIPTION  'Copyright 1988, mkj'
  671. STUB         'WINSTUB.EXE'
  672. CODE         LOADONCALL   MOVEABLE  DISCARDABLE
  673. DATA         MOVEABLE     SINGLE
  674. HEAPSIZE     2048
  675. CODE         MOVEABLE
  676. SEGMENTS    _INIT      PRELOAD        MOVEABLE      DISCARDABLE
  677.             HELPLIB    MOVEABLE       LOADONCALL    DISCARDABLE
  678.  
  679. EXPORTS
  680.        Screen        @1
  681.        Topics        @2
  682.        ScreenDlgProc @3
  683.        ScreenWndProc @4
  684.        TopicsDlgProc @5
  685.  
  686.  
  687. [LISTING EIGHT]
  688.  
  689. #
  690. # FILE: helplib
  691. # PURPOSE: make file for the helplib DLL
  692. #
  693. COMP  =  -c -Alnw  -Gsw -Zp -Os -FPa -W2 -D LINT_ARGS
  694. OBJS  = helplib.obj helpdlg.obj libinita.obj libinitc.obj helplib.res
  695. LOBJS = helplib+helpdlg+libinita+libinitc
  696.  
  697. .rc.res:
  698.   rc -r $*.rc
  699.  
  700. .asm.obj:
  701.   masm $*;
  702.  
  703. helplib.res:        helplib.rc helplib.h vsruntim.asc caveats.asc \
  704.                cookbook.asc ref.asc help.dlg topics.dlg
  705.  
  706. helplib.obj:        helplib.c helplib.h prothelp.h
  707.     cl $(COMP) -NT $* $*.c
  708.  
  709. helpdlg.obj:        helpdlg.c helplib.h prothelp.h
  710.     cl $(COMP) -NT HELPLIB $*.c
  711.  
  712. libinita.obj:       libinita.asm
  713.     masm $*;
  714.  
  715. libinitc.obj:           libinitc.c
  716.     cl $(COMP) -NT _INIT $*.c
  717.  
  718. helplib.exe: $(OBJS) helplib.def
  719.     link4 $(LOBJS),helplib.exe/align:16,/map/li,mwinlibc mlibw mlibca  /NOE  ,helplib.def
  720.     rc     helplib.res helplib.exe
  721.     implib helplib.lib helplib.def
  722.  
  723.  
  724. [LISTING NINE]
  725.  
  726.  /**********************************************************************
  727.  * FILE: helpdemo.c
  728.  * PURPOSE: to demonstrate the use of the helplib DLL
  729.  **********************************************************************/
  730. #include <windows.h>
  731. #include "helpdemo.h"
  732.  
  733. HANDLE        hInstance;         /* The Instance handle */
  734. char          szClass[10];       /* Window class name (see the .rc file) */
  735. char          szTitle[40];       /* Window title (see the .rc file) */
  736. char          szAbout[40];       /* About box string (see the .rc file */
  737.  
  738. static HWND   hWnd;
  739.  
  740. long FAR PASCAL WndProc (HWND, unsigned, WORD, LONG);
  741. BOOL NEAR       Initialize( HANDLE, int );
  742.  /***********************************************************************
  743.  *Application main program.  
  744.  ***********************************************************************/
  745. int PASCAL WinMain( hInst, hPrevInst, lpszCmdLine, nCmdShow )
  746.      HANDLE     hInst;          /* Our instance handle */
  747.      HANDLE     hPrevInst;      /* Previous instance of this application */
  748.      LPSTR      lpszCmdLine;    /* Pointer to any command line params */
  749.      int        nCmdShow;       /* Parameter to use for first ShowWindow */
  750.      {
  751.       MSG     msg;              /* Message structure */
  752.       HANDLE     hAccel;        /* Accelerator handle */
  753.       /* Save our instance handle in a global variable */
  754.       hInstance = hInst;
  755.       /* Initialize application, quit if any errors */
  756.       if( ! Initialize( hPrevInst, nCmdShow ) )
  757.                  {return FALSE;
  758.                  }
  759.       /* Main message processing loop.  Get each message, then translate 
  760.        * keyboard messages and finally dispatch each message to its window 
  761.        * function. 
  762.        */
  763.        hAccel = LoadAccelerators(hInstance,szClass);
  764.        while( GetMessage( &msg, NULL, 0, 0 ) )
  765.             {if (!TranslateAccelerator(hWnd, hAccel, &msg))
  766.                   {TranslateMessage( &msg );
  767.                    DispatchMessage( &msg );
  768.                   }
  769.             }
  770.       return msg.wParam;
  771.      }
  772.  /************************************************************************
  773.  *Initialize the application.  
  774.  *************************************************************************/
  775.  BOOL NEAR Initialize( hPrevInst, nCmdShow )
  776.      HANDLE     hPrevInst;         /* Previous instance handle, 0 if first */
  777.      int     nCmdShow;             /* Parameter from WinMain for ShowWindow */
  778.      {
  779.       WNDCLASS    WndClass;        /* Class structure for RegisterClass */
  780.       HMENU       hMenu;           /* Handle to the (system) menu */
  781.       if( ! hPrevInst ) {
  782.            /* Initialization for first instance only */
  783.            /* Load strings from resource file */
  784.            LoadString( hInstance, IDS_CLASS,    szClass,    sizeof(szClass) );
  785.            LoadString( hInstance, IDS_TITLE,    szTitle,    sizeof(szTitle) );
  786.            /* Register our window class */
  787.            WndClass.style            = CS_HREDRAW | CS_VREDRAW;
  788.            WndClass.lpfnWndProc      = WndProc;
  789.            WndClass.cbClsExtra       = 0;
  790.            WndClass.cbWndExtra       = 0;
  791.            WndClass.hInstance        = hInstance;
  792.            WndClass.hIcon            = LoadIcon( NULL, IDI_APPLICATION );
  793.            WndClass.hCursor          = LoadCursor( NULL, IDC_ARROW );
  794.            WndClass.hbrBackground    = COLOR_WINDOW + 1;
  795.            WndClass.lpszMenuName     = szClass;
  796.            WndClass.lpszClassName    = szClass;
  797.            if( ! RegisterClass( &WndClass ) )
  798.                return FALSE;
  799.           }
  800.       else
  801.          {/* Initialization for subsequent instances only */
  802.            /* Copy data from previous instance */
  803.            GetInstanceData( hPrevInst, szClass,    sizeof(szClass) );
  804.            GetInstanceData( hPrevInst, szTitle,    sizeof(szTitle) );
  805.           }
  806.       /* Initialization for every instance */
  807.  
  808.       /* Create the window  */
  809.       hWnd = CreateWindow(
  810.            szClass,          /* Class name */
  811.            szTitle,          /* Window title */
  812.            WS_OVERLAPPEDWINDOW             ,      /* window style */
  813.            CW_USEDEFAULT,    /* x */
  814.            0,                /* y */
  815.            CW_USEDEFAULT,    /* x width */
  816.            0,                /* y width */
  817.            NULL,             /* Parent hWnd (none for top-level) */
  818.            NULL,             /* Menu handle */
  819.            hInstance,        /* Owning instance handle */
  820.            NULL              /* Parameter to pass in WM_CREATE (none) */
  821.        );
  822.  
  823.  /* Insert "About..." into system menu */
  824.       LoadString( hInstance, IDS_ABOUT,    szAbout,    sizeof(szAbout) );
  825.       hMenu = GetSystemMenu(hWnd, FALSE);
  826.       ChangeMenu(hMenu, 0, NULL, 999, MF_APPEND | MF_SEPARATOR);
  827.       ChangeMenu(hMenu, 0, (LPSTR)szAbout, IDS_ABOUT, MF_APPEND | MF_STRING);
  828.  
  829.       /* Make the window visible  */
  830.       ShowWindow( hWnd, nCmdShow );
  831.  
  832.       /* Got all the information, update our display */
  833.       UpdateWindow( hWnd );
  834.  
  835.       return TRUE;
  836.      }
  837.  
  838.  
  839. [LISTING TEN]
  840.  
  841.  /***************************************************************************
  842.  * FILE: wndproc.c
  843.  * PURPOSE: The functions WndProc and About for the helplib DLL demo.
  844.  ***************************************************************************/
  845. #include "windows.h"
  846. #include "helpdemo.h"
  847. extern HANDLE hInstance;
  848.  /******************* Message function prototypes *******************/
  849. extern   VOID   HelpDemoMsg  ( HWND, WORD, LONG );
  850.  /******************* local function prototype **********************/
  851. BOOL NEAR           paint  ( HWND );
  852. long FAR PASCAL     WndProc( HWND, unsigned, WORD, LONG );
  853. BOOL FAR PASCAL     AboutDlgProc( HWND, unsigned, WORD, LONG );
  854. long FAR PASCAL WndProc( hWnd, message, wParam, lParam )
  855.      HWND hWnd;
  856.      unsigned message;
  857.      WORD wParam;
  858.      LONG lParam;
  859.      {
  860.       FARPROC lpprocAbout;
  861.       switch (message)
  862.            {
  863.             case WM_SYSCOMMAND:
  864.                  switch (wParam)
  865.                  {
  866.                   case IDS_ABOUT:
  867.                        /* Bind callback function with module instance */
  868.                        lpprocAbout = MakeProcInstance( (FARPROC)AboutDlgProc, 
  869.                                                        hInstance);
  870.                        DialogBox( hInstance, MAKEINTRESOURCE(ABOUTBOX), hWnd, 
  871.                                                        lpprocAbout );
  872.                        FreeProcInstance( (FARPROC)AboutDlgProc );
  873.                        break;
  874.                   default:
  875.                        return DefWindowProc( hWnd, message, wParam, lParam );
  876.                        }
  877.                  break;
  878.             case WM_COMMAND:
  879.                  switch(wParam)
  880.                  {
  881.                   case IDM_HELP:
  882.                        HelpDemoMsg (hWnd, wParam, lParam);
  883.                        break;
  884.                  }
  885.             case WM_PAINT:
  886.                  paint( hWnd );
  887.                  break;
  888.             case WM_DESTROY:
  889.             case WM_CLOSE:
  890.                  PostQuitMessage( 0 );
  891.                  break;
  892.             default:
  893.                  return DefWindowProc( hWnd, message, wParam, lParam );
  894.                  break;
  895.            }
  896.       return(0L);
  897.      }
  898.  /*************************************************************************
  899.  * Paint procedure (for processing of WM_PAINT messages)
  900.  **************************************************************************/
  901. BOOL   NEAR  paint ( hWnd )
  902.      HWND hWnd;
  903.      {
  904.       PAINTSTRUCT ps;
  905.       BeginPaint(hWnd,&ps);
  906.       EndPaint(hWnd,&ps);
  907.       return TRUE;
  908.      }
  909.  /**************************************************************************
  910.  * About Box
  911.  **************************************************************************/
  912. BOOL FAR PASCAL AboutDlgProc( hDlg, message, wParam, lParam )
  913.      HWND hDlg;
  914.      unsigned message;
  915.      WORD wParam;
  916.      LONG lParam;
  917.      {
  918.       if (message == WM_COMMAND)
  919.            {EndDialog( hDlg, TRUE );
  920.             return TRUE;
  921.            }
  922.       else if (message == WM_INITDIALOG)
  923.            return TRUE;
  924.       else return FALSE;
  925.      }
  926.  
  927.  
  928. [LISTING ELEVEN]
  929.  
  930.  /***************************************************************************
  931.  * The message functions.
  932.  ***************************************************************************/
  933. #include "windows.h"
  934. #include "helpdemo.h"
  935. #include "helplib.h"          /* library's help file */
  936. #include "prothelp.h"         /* prototypes for library's functions */
  937.  
  938. extern HANDLE hInstance;
  939.  
  940.  /******************* local function prototypes *******************/
  941. VOID   HelpDemoMsg  ( HWND, WORD, LONG );
  942.  
  943.  /**************************************************************************/
  944. VOID    HelpDemoMsg( hWnd, wParam, lParam )
  945.      HWND hWnd;
  946.      WORD wParam;
  947.      LONG lParam;
  948.     {SCREEN sc;
  949.      sc.wStart = VSRUNTIME;
  950.      sc.wEnd = REF;
  951.      Topics(&sc);
  952.      }
  953.  
  954. [LISTING TWELVE]
  955.  
  956. /**************************************************************************
  957.  * FILE: prothelp.h
  958.  * PURPOSE:function prototypes for the helplib DLL
  959.  *************************************************************************/
  960. #ifndef   HELPDLG
  961.   #define HELPDLG extern
  962. #endif
  963. #ifndef   HELPLIB
  964.   #define HELPLIB extern
  965. #endif
  966.  
  967. HELPLIB BOOL  FAR PASCAL  Screen          ( LPSCREEN );
  968. HELPLIB VOID  FAR PASCAL  Topics          ( LPSCREEN );
  969. HELPDLG BOOL  FAR PASCAL  ScreenDlgProc   ( HWND, WORD, WORD, LONG );
  970. HELPDLG BOOL  FAR PASCAL  TopicsDlgProc   ( HWND, WORD, WORD, LONG );
  971. HELPDLG LONG  FAR PASCAL  ScreenWndProc   ( HWND, WORD, WORD, LONG );
  972. extern LPSTR  FAR PASCAL  lstrcpy         ( LPSTR, LPSTR );
  973. extern int    FAR PASCAL  lstrlen         ( LPSTR );
  974.  
  975.  
  976. [LISTING THIRTEEN]
  977.  
  978. /*************************************************************************
  979.  * FILE: helpdemo.h
  980.  * PURPOSE: include file for the help DLL demonstration window
  981.  *************************************************************************/
  982.  
  983. /************** strings **************************************************/
  984. #define    IDS_CLASS              0  /* String Table ID for the Class Name */
  985. #define    IDS_TITLE              1  /* String Table ID for the Title */
  986. #define    IDS_ABOUT              2  /* String Table ID for the About box */
  987.  
  988. /************** menus ****************************************************/
  989. #define     ABOUTBOX          3      /* About dialog resource ID */
  990. #define    IDM_HELP           1000   /* Menu resource ID */
  991.  
  992.  
  993. [LISTING FOURTEEN]
  994.  
  995. NAME         HELPDEMO
  996. DESCRIPTION  'Help DLL Demonstration, Copyright 1988, mkj'
  997. STUB         'WINSTUB.EXE'
  998. CODE         LOADONCALL  MOVEABLE  DISCARDABLE
  999. DATA         MOVEABLE    MULTIPLE
  1000. HEAPSIZE     2048
  1001. STACKSIZE    4096
  1002. EXPORTS
  1003.        WndProc        @1
  1004.        AboutDlgProc   @2
  1005.  
  1006.  
  1007.  
  1008. [LISTING FIFTEEN]
  1009.  
  1010.  /**********************************************************************
  1011.  * FILE: helpdemo.rc
  1012.  * PURPOSE: used with the helplib DLL for demonstration
  1013.  **********************************************************************/
  1014.  
  1015. #include <style.h>
  1016. #include "helpdemo.h"
  1017.  
  1018. STRINGTABLE
  1019. BEGIN
  1020.      IDS_CLASS           "HelpDemo"
  1021.      IDS_TITLE           "Help Demonstration"
  1022.      IDS_ABOUT           "About..."
  1023. END
  1024.  
  1025. ABOUTBOX DIALOG 22, 17, 154, 75
  1026. STYLE WS_POPUP | WS_DLGFRAME
  1027. BEGIN
  1028.      CTEXT "DLL Example"                      -1, 0,  5, 154, 8
  1029.      CTEXT "Help Library Demonstration"       -1,  0, 14, 154, 8
  1030.      CTEXT "Version 1.00"                     -1, 30, 34, 94, 8
  1031.      CTEXT "Copyright ) 1988, mkj"            -1,  0, 47,154, 9
  1032.      DEFPUSHBUTTON "Ok"                 IDOK, 61, 59, 32, 14, WS_GROUP
  1033. END
  1034.  
  1035. HelpDemo   MENU
  1036. BEGIN
  1037.   MENUITEM "\aF1=Help",                 IDM_HELP,HELP
  1038. END
  1039.  
  1040. HelpDemo  ACCELERATORS
  1041. BEGIN
  1042.    VK_F1,   IDM_HELP, VIRTKEY
  1043. END
  1044.  
  1045. [LISTING SIXTEEN]
  1046.  
  1047. TOPICS_BOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 28, 19, 206, 79
  1048. STYLE  WS_DLGFRAME | WS_POPUP
  1049. BEGIN
  1050.     CONTROL "", ID_LB_TOPICS, "listbox", LBS_NOTIFY | WS_BORDER | WS_VSCROLL | WS_CHILD | TABGRP, 12, 18, 144, 49
  1051.     CONTROL "&Help", IDOK, "button", BS_DEFPUSHBUTTON | WS_TABSTOP | WS_CHILD | TABGRP, 165, 17, 32, 14
  1052.     CONTROL "Cancel", IDCANCEL, "button", BS_PUSHBUTTON | WS_TABSTOP | WS_CHILD , 165, 43, 32, 14
  1053.     CONTROL "Help Topics on DLL's", 103, "static", SS_LEFT | WS_CHILD, 12, 5, 100, 11
  1054. END
  1055.  
  1056.  
  1057. [LISTING SEVENTEEN]
  1058.  
  1059. HELP_BOX DIALOG LOADONCALL MOVEABLE DISCARDABLE 10, 9, 262, 131
  1060. STYLE WS_BORDER | WS_CAPTION | WS_POPUP | WS_SYSMENU | WS_VISIBLE
  1061. CAPTION  "Help"
  1062. BEGIN
  1063. CONTROL "", ID_SCREEN_HELP, "Screen",  WS_BORDER | WS_CHILD | TABGRP, 9, 9, 234, 90
  1064. CONTROL "", ID_SCROLL_HELP, "scrollbar", SBS_VERT | WS_CHILD | WS_CLIPSIBLINGS, 242, 9, 8, 90
  1065. CONTROL "&Next", ID_NEXT_HELP, "button", BS_DEFPUSHBUTTON | WS_TABSTOP | WS_CHILD, 76, 105, 44, 16
  1066. CONTROL "&Previous", ID_PREVIOUS_HELP, "button", BS_PUSHBUTTON | WS_TABSTOP | WS_CHILD, 139, 105, 44, 16
  1067. CONTROL "Cancel", IDCANCEL, "button", BS_PUSHBUTTON | WS_TABSTOP | WS_CHILD, 201, 105, 44, 16
  1068. CONTROL "&Topics", ID_TOPICS_HELP, "button", BS_PUSHBUTTON | WS_TABSTOP | WS_CHILD, 14, 105, 44, 16
  1069. END
  1070.  
  1071.  
  1072. [LISTING EIGHTEEN]
  1073.  
  1074. #
  1075. # FILE: helpdemo
  1076. # PURPOSE: make file for the helplib DLL demo
  1077. #
  1078. COMP  = -c -AS -D LINT_ARGS -Os -Zp  -Gsw -FPa
  1079. ASM   =
  1080.  
  1081. .rc.res:
  1082.   rc -r $*.rc
  1083.  
  1084. .c.obj:
  1085.   cl $(COMP) $*.c
  1086.  
  1087. .asm.obj:
  1088.   masm $(ASM) $*;
  1089.  
  1090. helpdemo.res:    helpdemo.rc  helpdemo.h
  1091.  
  1092. helpdemo.obj:    helpdemo.c   helpdemo.h
  1093.  
  1094. wndproc.obj:     wndproc.c    helpdemo.h
  1095.  
  1096. msgs.obj:        msgs.c          helpdemo.h helplib.h prothelp.h
  1097.  
  1098. helpdemo.exe:    helpdemo.obj wndproc.obj msgs.obj helpdemo.res
  1099.  link4  helpdemo+wndproc+msgs,/align:16,/map/li,slibw slibca helplib /NOE /co  ,helpdemo.def
  1100.  rc helpdemo.res
  1101.  
  1102.  
  1103. [LISTING NINETEEN]
  1104.  
  1105. /*   **************************************
  1106.      FILE: helplib.act
  1107.      PURPOSE: example of specifying and loading
  1108.          the library at run-time instead of
  1109.          at link (link4). The code is written in 
  1110.          Actor, an object-oriented language for 
  1111.          developing MS-Windows applications.
  1112.      ************************************** */
  1113.      
  1114. /*   **************************************
  1115.      INITIALIZATION
  1116.      ************************************** */
  1117. /* define constants */
  1118. #define VSRUNTIME       300
  1119. #define CAVEATS         301
  1120. #define COOKBOOK        302
  1121. #define REF             303
  1122.  
  1123. #define A               500
  1124. #define B               501
  1125. #define C               502
  1126. !!
  1127.  
  1128. /* create a new C struct */
  1129. SCREEN := new(CStruct);
  1130. !!
  1131.  
  1132. init(SCREEN, #(
  1133.   int wScreen 1
  1134.   int wStart  1
  1135.   int wEnd    1
  1136. ));
  1137. !!
  1138. /* initialize help library */
  1139. HelpLib := new(Library);            /* create new library               */
  1140. HelpLib.name := "HELPLIB.EXE";      /* set the file name of the library */
  1141. add(HelpLib, #SCREEN, 0, #(1));     /* add the names of the exported
  1142.                                        functions in the library that you
  1143.                                        will call. The '0' is the return
  1144.                                        type (0=int,1=long), and the
  1145.                                        '#(1)' lists the arguments - one
  1146.                                        long variable                    */
  1147. !!
  1148. /* load library */
  1149. load(HelpLib);
  1150. !!
  1151. /*   **************************************
  1152.      BODY
  1153.      ************************************** */
  1154. /* fill C Struct */
  1155. SCREEN[#wStart] := VSRUNTIME;
  1156. SCREEN[#wEnd] := REF;
  1157. SCREEN[#wScreen] := CAVEATS;
  1158. !!
  1159. /* call DLL to put up help dialog */
  1160. pcall(HelpLib.procs[#SCREEN], lP(SCREEN));
  1161. freeHandle(SCREEN);
  1162. !!
  1163. /*   **************************************
  1164.      CLEAN-UP
  1165.      ************************************** */
  1166. /* free the library */
  1167. free(HelpLib);
  1168. !!
  1169.  
  1170.  
  1171. [EXAMPLE 1] 
  1172.  
  1173. caveats
  1174.  
  1175. As is usually the case in life, it takes a
  1176. little more to get a little more. This is 
  1177. certainly true with DLL's.  There are two big 
  1178. differences between code in a DLL and code in a 
  1179. standard runtime library under MS-DOS.  The 
  1180. first one is on the tip of the tongue of anyone 
  1181. who has ventured into the DLL domain.  This is 
  1182. the SS != DS issue.  The second concerns the 
  1183. use of global variables. 
  1184.  
  1185. Normally, when c code is compiled, it is 
  1186. assumed that the data segment (DS) is the same 
  1187. as the stack segment (SS).  This is valid when 
  1188. passing the address of a parameter to a 
  1189. function for the small (ie: one code segment 
  1190. and one data segment) and medium (ie: multiple 
  1191. code segments and one data segment) model, 
  1192. since only the 16-bit offset of addresses are 
  1193. passed. 
  1194.  
  1195. DLL's have their own data segment and use the 
  1196. stack of the caller.  In this case, the stack 
  1197. segment does not equal the data segment 
  1198. (SS!=DS) and the 16-bit offsets are not valid 
  1199. addresses, since all automatic variables (ie: 
  1200. parameters and local variables) are kept on the 
  1201. stack, and all others (ie: global and static 
  1202. variables) are contained in the data segment. 
  1203. This means that any addresses passed to a 
  1204. function must contain both the segment and 
  1205. offset (ie: 32-bit far pointers). 
  1206.  
  1207. Because of this, some of the standard c runtime 
  1208. library functions cannot be used.  These are 
  1209. listed in an appendix of Microsoft's Software 
  1210. Development Kit (SDK) for Windows.  In general, 
  1211. any of the buffered io functions (eg: fprintf, 
  1212. fscanf, sscanf, etc.), exec (eg: execlp, execv, 
  1213. etc.), and spawn (eg: spawnl, spawnv, etc.) 
  1214. functions are off limits. 
  1215.  
  1216. Because programs in DOS need not be re-entrant, 
  1217. it is common to generously sprinkle code with 
  1218. global veriables.  This can be a source of 
  1219. grief to the person who wishes to convert 
  1220. existing code to work in a DLL.  Although code 
  1221. is not re-entrant, the data is.  A DLL has only 
  1222. one data segment which is shared by all 
  1223. applications.  Don't expect a variable that is 
  1224. set by one function of the DLL to contain the 
  1225. set value in another function.  A common case 
  1226. are plotting libraries.  Usually the sequence 
  1227. of calls consist of setting plot variables, 
  1228. graphing the plot using the plot variables set 
  1229. previously, then performing any cleanup. 
  1230.  
  1231. Putting the plotting variables in global memory 
  1232. assumes each application that makes this series 
  1233. of calls has it's own data area to hold these 
  1234. variables.  If these retines reside in a DLL, 
  1235. then the global variable that sets the x-origin 
  1236. within the DLL is the same variable used by any 
  1237. application that calls this routine.  For 
  1238. example,  if two applications (A and B) co-
  1239. exist and application A makes calls to set the 
  1240. plotting variables, then B does the same before 
  1241. A can call to plot,  the variables used by the 
  1242. DLL will be set to B's preferences.
  1243.  
  1244. [EXAMPLE 2]
  1245.  
  1246. cookbook
  1247.  
  1248. Steps To Follow When Creating a  DLL:
  1249.  
  1250. 1. Create the resource file.
  1251.  
  1252. 2. Create the library source files.
  1253.  
  1254. 3. Make sure you have an initialization function.
  1255.  
  1256. 4. Create the module definition file.
  1257.  
  1258. 5. Create a make file to:
  1259.  
  1260.    a. Compile the library and initialization source files.
  1261.  
  1262.    b. Use the rc compiler to compile any resources.
  1263.  
  1264.    c. Use the link4 linker to create the .EXE file.
  1265.  
  1266.    d. Attach the resources to the .EXE file.
  1267.  
  1268.    e. Use the implib tool to create an import library.
  1269.  
  1270.  
  1271. [EXAMPLE 3]
  1272.  
  1273. references
  1274.  
  1275. Two books are definite musts:
  1276.  
  1277. Programming Windows by Charles Petzold
  1278. Microsoft Press: 1988
  1279.  
  1280. 852 pages jam-packed with Windows programming 
  1281. tips and useful code.  This is an incredible 
  1282. source for Windows developers. 
  1283.  
  1284. Inside OS/2 by Gordon Letwin
  1285. Microsoft Press: 1988
  1286.  
  1287. 289 pages from the chief architect for systems 
  1288. software at Microsoft.  This book is great for 
  1289. getting a feel for what OS/2 has to offer, and 
  1290. the philosophy behind it.  It also gives a good 
  1291. feeling for the differences between the API for 
  1292. Windows and OS/2 without getting bogged down in 
  1293. the code.
  1294.  
  1295.  
  1296. [EXAMPLE 4]
  1297.  
  1298. versus run-time libraries
  1299.  
  1300. In the MS-DOS world, code is compiled and
  1301. linked with external libraries or object 
  1302. modules to create an executable.  Frequently, 
  1303. routines in libraries are generic, consisting 
  1304. of often used functions. An example of this is 
  1305. the run-time library included with the 
  1306. compiler.  Each executable that calls a routine 
  1307. from the library contains a copy of the code 
  1308. for that function. Under typical DOS  single-
  1309. tasking conditions, and assuming it doesn't 
  1310. matter how large the executable file is, run-
  1311. time libraries are just fine. 
  1312.  
  1313. Having each application carry around a copy of 
  1314. common code is inefficient in a multitasking 
  1315. system such as Windows.  Windows is an 
  1316. operating environment that sits on top of DOS 
  1317. and creates a non-preemptive event driven 
  1318. multatasking environment for its applications.  
  1319. In fact, with Windows, this is even more 
  1320. important since Windows is constrained to sit 
  1321. on top of DOS, and the environment that DOS 
  1322. sits in only allows 640K of memory (assuming 
  1323. no expanded memory).  In Windows, if multiple 
  1324. instances of the same application are loaded, 
  1325. they will share the same code space.  However, 
  1326. if multiple applications are loaded, code is 
  1327. not shared.  If each application calls the 
  1328. same function to smooth data from a run-time 
  1329. library, then Windows will allocate code space 
  1330. For the smooth function for each application.  
  1331. As any one who has run multiple applications 
  1332. under Windows knows, memory is to Windows what 
  1333. water is to the desert - a precious resource 
  1334. that should not be waisted. 
  1335.  
  1336. If a function resides in a DLL, then only one 
  1337. copy will be loaded no matter how many 
  1338. applications call it.  This also keeps the 
  1339. application's executable small by keeping the 
  1340. common code out of each application.  Not only 
  1341. that, but since the code is dynamically loaded 
  1342. at run time, as long as the parameter sequence 
  1343. of the function call does not change, the 
  1344. innards of a function in a dll can be changed 
  1345. without forcing the application's executable 
  1346. to be recompiled and relinked. 
  1347.  
  1348. Loading the library at run time allows other 
  1349. exciting opportunities.  Some packages allow 
  1350. functions in a dll to be called within their 
  1351. program.  This includes Actor from Whitewater, 
  1352. Excel from Microsoft, and SQL Windows from 
  1353. Gupta.  This allows the developer to use his 
  1354. warm and comfy functions in extremely powerful 
  1355. existing applications. But wait, there's more! 
  1356. DLL's need not contain any code or data at 
  1357. all! They can also be completely made of 
  1358. resources such as fonts, bitmaps, icons, or 
  1359. cursors.
  1360.